package jogs.net.gameroomserver;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;

public class GRSClientHandler extends Thread
{
  private Socket clientSocket; 
  private GameRoomServer grs; // parent
  private BufferedReader in;
  private PrintStream out; 
  private boolean disconnected; 
  private boolean metaserver;

  private String username; 
  
  public GRSClientHandler(Socket _clientSocket, GameRoomServer _grs, boolean _metaserver)
  {
    in = null;
    out = null; 
    clientSocket = _clientSocket; 
    grs = _grs; 
    disconnected = false; 
    metaserver = _metaserver; 
  }

  public void send(String msg)
  {
    if (out != null) out.println(msg);
  }

  public void run()
  {
    if (metaserver) 
      run_metaserver(); 

    try
    {
      in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); 
      out = new PrintStream(clientSocket.getOutputStream()); 
      int authenticated = 0;
      
      while (authenticated == 0)
      {
        out.println("AUTHENTICATE");//change later to @COMMAND: format
        String un = in.readLine(); 
        String pw = in.readLine(); 
        
        if (un == null || pw == null)
        {
          System.out.println("bogus data from metaserver.. metaserver died? killing this GRSClientHandler..");
          return;
        }

        authenticated = grs.authenticate(un, pw);
        System.out.println("authenticated = " + authenticated); 
        username = un;  
        if (authenticated != 1 && authenticated != 2)
          System.out.println("Auth failed with authenticated="+authenticated+",un="+un+",pw="+pw+"###"); 
      }
      //change later to @COMMAND: format
      out.println("LOGINSUCC"); 

      if (authenticated == 1)
      {
        // it's the metaserver
      	GRSClientHandler metaServer = new GRSClientHandler(clientSocket, grs, true);
        grs.setMetaServer(metaServer); 
        metaServer.start(); 
        return;
      }

      // else, treat this as a regular client 
      
      
      grs.addClient(this);
      //grs.broadcast("@ENTERED:" + username); 
      
      // add method 
      
      String line = ""; 
      while (!disconnected && line != null)
      {
        line = in.readLine(); 
        processline(line);
        //grs.broadcast(username + ": " + line);  
      }
    }
    catch(Exception e)
    {
      System.out.println("Caught exception in client handler.. client stopping."); 
      e.printStackTrace(); 
      disconnected = true;  
    }
    disconnect();
    
  }

  void processline(String input)
  {
  	//logger.log(Level.INFO, "Direct message from {0}", this.getName());
    String details = null;
    String command = null;
    
    
    //all commands start with a @ and end with a : 
    int begin = input.indexOf('@');
    int end = input.indexOf(':');
    
    //if @ and : are not in message than it is not a command
    if(begin == -1 || end == -1)
    {
      this.send("@ERROR:Not a valid command");
      return;
    }
    
    //get the command out of the message
    command = input.substring(begin, end);
    
    //if command has details
    if(input.length() > end+1)
      details = input.substring(end+1);
    
    //process the command
    
    if(command.equals("@CHAT"))
    {
      grs.broadcast("@CHAT:" + username + ": " + details);
    }
    else if(command.equals("@PCHAT"))
    {
      //To be done soon.
    }
    else if(command.equals("@JOIN"))
    {
      
      /*if(g == null)
      {
        this.send("@ERROR:there is no game by the name of " + details);
        return;
      }*/
    }
    else if (command.equals("@SIT"))
    {
      String info = grs.handleSit(details, username); 
      if (info == null)
      {
        System.out.println("handleSit returned null"); 
        out.println("@ERROR_SIT:No such table " + details); 
      }
      else
        out.println("@OKSIT:" + info); 
    }
    else if(command.equals("@CREATE"))
    {
      ///Do This.
      /*
       * format should be @CREATE:tableName,GameType,MaxPlayers
       * if(game != null)
      {
        this.send("@ERROR:already in game");
        return;
      }
      String[] arg = details.split(",");
      String tableName = Game.getNextGameName();
      Game g = parent.createGame(arg[0], tableName, Integer.parseInt(arg[1]), this);
      if(g == null)
      {
        this.send("@ERROR:problem creating game");
        return;
      }
      parent.joinGame(g.getName(), this);
      setGame(g);*/
      
    }
    else if(command.equals("@LEAVE"))
    {
      disconnected = true;
    }
    else if(command.equals("@DISC"))
    {
    	disconnected = true;
    }
    else
    {
      this.send("@ERROR:Not Valid Account");
    }
  }
  
  void disconnect()
  {
  	try
  	{
  		in.close();
  		out.close();
  		clientSocket.close();
  	}
  	catch(IOException e)
  	{
  		
  	}
  	grs.leave(this);
  	disconnected = true;
  }
  
  synchronized boolean disconnected()
  {
  	return disconnected;
  }
  
  synchronized String getUsername()
  {
  	return username;
  }
  
  void run_metaserver()
  {
    System.out.println("Starting metaserver client handler."); 

    try
    {
      in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); 
      out = new PrintStream(clientSocket.getOutputStream()); 
    
      String line = ""; 
      while (line != null)
      {
        line = in.readLine(); 
        
        // respond to the request from the metaserver 

        handle_ms_request(line); 
      }
    }
    catch(Exception e)
    {
      System.out.println("Caught exception in client handler.. client stopping."); 
      e.printStackTrace(); 
      disconnected = true;  
    }
  }

  // --- 

  boolean handle_ms_request(String line)
  {
    if(line == null)
      return true;
    String details = null;
    String command = null;
  
    //all commands start with a @ and end with a : 
    int begin = line.indexOf('@');
    int end = line.indexOf(':');
    
    //if @ and : are not in message than it is not a command
    if(begin == -1 || end == -1)
    {
      //this.send("@ERROR:Not a valid command");
      return false;
    }
    
    //get the command out of the message
    command = line.substring(begin, end);
    
    //if command has details
    if(line.length() > end+1)
      details = line.substring(end+1);

    if (command.equals("@GET_CLIENT_COUNT"))
      out.println("" + grs.getClientCount()); 
    else if (command.equals("@GET_NAME"))
      out.println(grs.getName()); 
    else if (command.equals("@ADDKEYPASS"))
    {
      String[] parts = details.split(","); 
      String user = parts[0];
      String keypass = parts[1]; 
      System.out.println("Adding keypass user="+ user + ",keypass=" + keypass + "..."); 
      grs.addKeyPass(user, keypass); 
      System.out.println("Done. "); 
      out.println("@OK_ADDKEYPASS:");
    }
    else 
      return false; 

    return true; 
  }
}
